home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 24
/
Amiga Format AFCD24 (Feb 1998, Issue 108).iso
/
-in_the_mag-
/
emulation
/
uae
/
uae-0.4.3
/
dos-grx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-20
|
13KB
|
528 lines
/*
* UAE - The Un*x Amiga Emulator
*
* DOS GRX lib svga interface.
*
* (c) 1995 Bernd Schmidt
* (c) 1996 Gustavo Goedert
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include <grx.h>
#include <pc.h>
#include <go32.h>
#include <dpmi.h>
#include "config.h"
#include "amiga.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "keyboard.h"
#include "xwin.h"
#include "keybuf.h"
#define R_WEIGHT 5
#define G_WEIGHT 5
#define B_WEIGHT 5
#define SCANCODE_CURSORUP 72
#define SCANCODE_CURSORLEFT 75
#define SCANCODE_CURSORRIGHT 77
#define SCANCODE_CURSORDOWN 80
#define SCANCODE_CURSORUPLEFT 71
#define SCANCODE_CURSORUPRIGHT 73
#define SCANCODE_CURSORDOWNLEFT 79
#define SCANCODE_CURSORDOWNRIGHT 81
#define SCANCODE_CURSORBLOCKUP 103
#define SCANCODE_CURSORBLOCKLEFT 105
#define SCANCODE_CURSORBLOCKRIGHT 106
#define SCANCODE_CURSORBLOCKDOWN 108
#define SCANCODE_KEYPAD0 82
#define SCANCODE_KEYPAD1 79
#define SCANCODE_KEYPAD2 80
#define SCANCODE_KEYPAD3 81
#define SCANCODE_KEYPAD4 75
#define SCANCODE_KEYPAD5 76
#define SCANCODE_KEYPAD6 77
#define SCANCODE_KEYPAD7 71
#define SCANCODE_KEYPAD8 72
#define SCANCODE_KEYPAD9 73
#define SCANCODE_KEYPADENTER 96
#define SCANCODE_KEYPADPLUS 78
#define SCANCODE_KEYPADMINUS 74
#define SCANCODE_Q 16
#define SCANCODE_W 17
#define SCANCODE_E 18
#define SCANCODE_R 19
#define SCANCODE_T 20
#define SCANCODE_Y 21
#define SCANCODE_U 22
#define SCANCODE_I 23
#define SCANCODE_O 24
#define SCANCODE_P 25
#define SCANCODE_A 30
#define SCANCODE_S 31
#define SCANCODE_D 32
#define SCANCODE_F 33
#define SCANCODE_G 34
#define SCANCODE_H 35
#define SCANCODE_J 36
#define SCANCODE_K 37
#define SCANCODE_L 38
#define SCANCODE_Z 44
#define SCANCODE_X 45
#define SCANCODE_C 46
#define SCANCODE_V 47
#define SCANCODE_B 48
#define SCANCODE_N 49
#define SCANCODE_M 50
#define SCANCODE_ESCAPE 1
#define SCANCODE_ENTER 28
#define SCANCODE_RIGHTCONTROL 97
#define SCANCODE_CONTROL 97
#define SCANCODE_RIGHTALT 100
#define SCANCODE_LEFTCONTROL 29
#define SCANCODE_LEFTALT 56
#define SCANCODE_SPACE 57
#define SCANCODE_F1 59
#define SCANCODE_F2 60
#define SCANCODE_F3 61
#define SCANCODE_F4 62
#define SCANCODE_F5 63
#define SCANCODE_F6 64
#define SCANCODE_F7 65
#define SCANCODE_F8 66
#define SCANCODE_F9 67
#define SCANCODE_F10 68
#define KEY_EVENTRELEASE 0
#define KEY_EVENTPRESS 1
#define SCANCODE_0 11
#define SCANCODE_1 2
#define SCANCODE_2 3
#define SCANCODE_3 4
#define SCANCODE_4 5
#define SCANCODE_5 6
#define SCANCODE_6 7
#define SCANCODE_7 8
#define SCANCODE_8 9
#define SCANCODE_9 10
#define SCANCODE_LEFTSHIFT 42
#define SCANCODE_RIGHTSHIFT 54
#define SCANCODE_TAB 15
#define SCANCODE_F11 87
#define SCANCODE_F12 88
#define SCANCODE_NEXT 81
#define SCANCODE_PRIOR 73
#define SCANCODE_BS 14
/*
#define SCANCODE_asciicircum 1
*/
#define SCANCODE_bracketleft 26
#define SCANCODE_bracketright 27
#define SCANCODE_comma 51
#define SCANCODE_period 52
#define SCANCODE_slash 53
#define SCANCODE_semicolon 39
#define SCANCODE_grave 40
#define SCANCODE_minus 12
#define SCANCODE_equal 13
#define SCANCODE_numbersign 41
#define SCANCODE_ltgt 43
#define SCANCODE_scrolllock 70
void (*DrawPixel)(int, xcolnr);
static char pixel_buffer[3200];
char *xlinebuffer;
long int xcolors[4096];
static int next_pos;
static bool next_double;
void prepare_line(int y, bool need_double)
{
next_pos = y;
next_double = need_double;
xlinebuffer = pixel_buffer;
}
void flush_line(void)
{
asm ("
cld
movl $_pixel_buffer, %esi
movl _next_pos, %ebx
cmpb $0, _use_dos_hicolor
je DRAWIC
movl $1600, %eax
mull %ebx
addl $0xd0000000, %eax
movl %eax, %edi
movl $400, %ecx
rep
movsl
cmpb $0, _next_double
je END
subl $1600, %esi
movl $400, %ecx
rep
movsl
jmp END
DRAWIC:
movl $800, %eax
mull %ebx
addl $0xd0000000, %eax
movl %eax, %edi
movl $200, %ecx
rep
movsl
cmpb $0, _next_double
je END
subl $800, %esi
movl $200, %ecx
rep
movsl
END:
");
}
static void DrawPixel8(int x, xcolnr col)
{
*(char *)xlinebuffer = col;
xlinebuffer += 1;
}
static void DrawPixel16(int x, xcolnr col)
{
*(short *)xlinebuffer = col;
xlinebuffer += 2;
}
void flush_screen(void)
{
}
static __inline__ unsigned long doMask(int p, int bits, int shift)
{
/* p is a value from 0 to 15 (Amiga color value)
* scale to 0..255, shift to align msb with mask, and apply mask */
unsigned long val = p * 0x11111111UL;
val >>= (32 - bits);
val <<= shift;
return val;
}
static void init_colors(void)
{
if (use_dos_hicolor) {
int i;
for(i=0; i<4096; i++) {
int r = i >> 8;
int g = (i >> 4) & 0xF;
int b = i & 0xF;
xcolors[i] = (doMask(r, R_WEIGHT, G_WEIGHT + B_WEIGHT)
| doMask(g, G_WEIGHT, B_WEIGHT)
| doMask(b, B_WEIGHT, 0));
}
} else {
/* This is kind of kludgy...
* Try to allocate as many different colors as possible. */
int step = 16, count = 0, col;
int allocated[4096];
memset(allocated,0,sizeof allocated);
while ((step/=2) > 0) {
int r, g, b;
for(r = 0; r < 16; r += step) {
for(g = 0; g < 16; g += step) {
for(b = 0; b < 16; b += step) {
int cnr = (r << 8) + (g << 4) + b;
if (++count == 256)
goto finished;
if (!allocated[cnr]) {
allocated[cnr] = true;
xcolors[cnr] = count-1;
GrSetColor(count-1, (r*255+7)/15, (g*255+7)/15, (b*255+7)/15);
}
}
}
}
}
finished:
for(col = 0; col < 4096; col++) {
int cnr = col;
if (!allocated[cnr]) {
int r = cnr >> 8;
int g = (cnr >> 4) & 0xF;
int b = cnr & 0xF;
int maxd = 4096,best = 0;
int c2;
for(c2 = 0; c2 < 4096; c2++)
if (allocated[c2]) {
int r2 = c2 >> 8;
int g2 = (c2 >> 4) & 0xF;
int b2 = c2 & 0xF;
int dist = abs(r2-r)*2 + abs(g2-g)*3 + abs(b2-b);
if (dist < maxd) {
maxd = dist;
best = c2;
}
}
cnr = best;
}
xcolors[col] = xcolors[cnr];
}
}
}
bool buttonstate[3] = { false, false, false };
int lastmx, lastmy;
bool newmousecounters = false;
static bool keystate[256];
static int scancode2amiga(int scancode)
{
switch(scancode) {
case SCANCODE_A: return AK_A;
case SCANCODE_B: return AK_B;
case SCANCODE_C: return AK_C;
case SCANCODE_D: return AK_D;
case SCANCODE_E: return AK_E;
case SCANCODE_F: return AK_F;
case SCANCODE_G: return AK_G;
case SCANCODE_H: return AK_H;
case SCANCODE_I: return AK_I;
case SCANCODE_J: return AK_J;
case SCANCODE_K: return AK_K;
case SCANCODE_L: return AK_L;
case SCANCODE_M: return AK_M;
case SCANCODE_N: return AK_N;
case SCANCODE_O: return AK_O;
case SCANCODE_P: return AK_P;
case SCANCODE_Q: return AK_Q;
case SCANCODE_R: return AK_R;
case SCANCODE_S: return AK_S;
case SCANCODE_T: return AK_T;
case SCANCODE_U: return AK_U;
case SCANCODE_V: return AK_V;
case SCANCODE_W: return AK_W;
case SCANCODE_X: return AK_X;
case SCANCODE_Y: return AK_Y;
case SCANCODE_Z: return AK_Z;
case SCANCODE_0: return AK_0;
case SCANCODE_1: return AK_1;
case SCANCODE_2: return AK_2;
case SCANCODE_3: return AK_3;
case SCANCODE_4: return AK_4;
case SCANCODE_5: return AK_5;
case SCANCODE_6: return AK_6;
case SCANCODE_7: return AK_7;
case SCANCODE_8: return AK_8;
case SCANCODE_9: return AK_9;
case SCANCODE_KEYPAD0: return AK_NP0;
case SCANCODE_KEYPAD1: return AK_NP1;
case SCANCODE_KEYPAD2: return AK_NP2;
case SCANCODE_KEYPAD3: return AK_NP3;
case SCANCODE_KEYPAD4: return AK_NP4;
case SCANCODE_KEYPAD5: return AK_NP5;
case SCANCODE_KEYPAD6: return AK_NP6;
case SCANCODE_KEYPAD7: return AK_NP7;
case SCANCODE_KEYPAD8: return AK_NP8;
case SCANCODE_KEYPAD9: return AK_NP9;
case SCANCODE_F1: return AK_F1;
case SCANCODE_F2: return AK_F2;
case SCANCODE_F3: return AK_F3;
case SCANCODE_F4: return AK_F4;
case SCANCODE_F5: return AK_F5;
case SCANCODE_F6: return AK_F6;
case SCANCODE_F7: return AK_F7;
case SCANCODE_F8: return AK_F8;
case SCANCODE_F9: return AK_F9;
case SCANCODE_F10: return AK_F10;
case SCANCODE_BS: return AK_BS;
case SCANCODE_CONTROL: return AK_CTRL;
case SCANCODE_TAB: return AK_TAB;
case SCANCODE_LEFTALT: return AK_LALT;
case SCANCODE_RIGHTALT: return AK_RALT;
case SCANCODE_ENTER: return AK_RET;
case SCANCODE_SPACE: return AK_SPC;
case SCANCODE_LEFTSHIFT: return AK_LSH;
case SCANCODE_RIGHTSHIFT: return AK_RSH;
case SCANCODE_ESCAPE: return AK_ESC;
case SCANCODE_CURSORBLOCKUP: return AK_UP;
case SCANCODE_CURSORBLOCKDOWN: return AK_DN;
case SCANCODE_CURSORBLOCKLEFT: return AK_LF;
case SCANCODE_CURSORBLOCKRIGHT: return AK_RT;
case SCANCODE_F11: return AK_BACKSLASH;
/*
case SCANCODE_asciicircum: return AK_00;
*/
case SCANCODE_bracketleft: return AK_LBRACKET;
case SCANCODE_bracketright: return AK_RBRACKET;
case SCANCODE_comma: return AK_COMMA;
case SCANCODE_period: return AK_PERIOD;
case SCANCODE_slash: return AK_SLASH;
case SCANCODE_semicolon: return AK_SEMICOLON;
case SCANCODE_grave: return AK_QUOTE;
case SCANCODE_minus: return AK_MINUS;
case SCANCODE_equal: return AK_EQUAL;
/* This one turns off screen updates. */
case SCANCODE_scrolllock: return AK_inhibit;
#if 0 /* No unique scancode for these yet. I need a Win95 keyboard :-( */
case SCANCODE_NEXT: return AK_RAMI; /* PgUp mapped to right amiga */
case SCANCODE_PRIOR: return AK_LAMI; /* PgDn mapped to left amiga */
#endif
/*#ifdef KBD_LANG_DE*/
case SCANCODE_numbersign: return AK_NUMBERSIGN;
case SCANCODE_ltgt: return AK_LTGT;
/*#endif*/
}
return -1;
}
static void my_kbd_handler(void)
{
int scancode, newstate, akey;
scancode = inportb(0x60);
newstate = !(scancode & 0x80);
scancode = scancode & 0x7f;
outportb(0x20, 0x20);
akey = scancode2amiga(scancode);
if (scancode == SCANCODE_F12)
specialflags |= SPCFLAG_BRK;
if (keystate[scancode] == newstate)
return;
keystate[scancode] = newstate;
if (akey == -1)
return;
if (newstate == KEY_EVENTPRESS) {
if (akey == AK_inhibit)
inhibit_frame ^= 1;
else
record_key (akey << 1);
} else
record_key ((akey << 1) | 1);
/* "Affengriff" */
if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
MC68000_reset();
}
_go32_dpmi_seginfo old_kbd_handler, new_kbd_handler;
int graphics_init(void)
{
int i, res;
_go32_dpmi_registers regs;
_go32_dpmi_get_protected_mode_interrupt_vector(9, &old_kbd_handler);
new_kbd_handler.pm_offset = (int)my_kbd_handler;
new_kbd_handler.pm_selector = _go32_my_cs();
res = _go32_dpmi_allocate_iret_wrapper(&new_kbd_handler);
if(res!=0) {
fprintf (stderr, "Error: Can't allocate iret_wrapper");
return 0;
}
res = _go32_dpmi_set_protected_mode_interrupt_vector(9, &new_kbd_handler);
if(res!=0) {
fprintf (stderr, "Error: Can't set protected mode interrupt vector");
return 0;
}
regs.x.ax=0;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, ®s);
if(regs.x.ax==0) {
fprintf (stderr, "Error: Mouse driver not present");
return 0;
}
if(use_dos_hicolor) {
GrSetMode(GR_width_height_color_graphics, 800, 600, 32768);
DrawPixel = DrawPixel16;
} else {
GrSetMode(GR_width_height_color_graphics, 800, 600, 256);
DrawPixel = DrawPixel8;
}
init_colors();
buttonstate[0] = buttonstate[1] = buttonstate[2] = false;
for(i = 0; i < 256; i++)
keystate[i] = false;
lastmx = lastmy = 0; newmousecounters = false;
return 1;
}
void graphics_leave(void)
{
GrSetMode(GR_default_text);
_go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_handler);
}
void handle_events(void)
{
_go32_dpmi_registers regs;
regs.x.ax=11;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, ®s);
lastmx += (short)regs.x.cx;
lastmy += (short)regs.x.dx;
regs.x.ax=3;
regs.x.ss=regs.x.sp=regs.x.flags=0;
_go32_dpmi_simulate_int(0x33, ®s);
buttonstate[0] = regs.x.bx & 1;
buttonstate[1] = regs.x.bx & 4;
buttonstate[2] = regs.x.bx & 2;
}
bool debuggable(void)
{
return false;
}
bool needmousehack(void)
{
return false;
}
void LED(int on)
{
}